﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using Redbrick.Silverlight.Collections;

namespace Redbrick.Silverlight.Controls
{
	public class VirtualizingCanvas : VirtualizingPanel, IScrollInfo
	{

		#region Consts & Settings


		#endregion Consts & Settings

		#region Declarations

		private Size _extent = new Size(0, 0);
		private Size _viewport = new Size(0, 0);
		private TranslateTransform _transform = new TranslateTransform();
		private List<UIElement> _realizedChildren =null;
		private IItemContainerGenerator _generator;
		private Size _assumedControlSize = new Size(50, 50);
		private Size _previousMeasureSize = new Size(0, 0);


		#endregion Declarations

		#region Constructor

		public VirtualizingCanvas()
		{

		}

		#endregion Constructor

		#region Methods

		protected override Size MeasureOverride(Size availableSize)
		{
			return base.MeasureOverride(availableSize);
		}
		protected override Size ArrangeOverride(Size finalSize)
		{
			return base.ArrangeOverride(finalSize);
		}



		public Rect MakeVisible(UIElement visual, Rect rectangle)
		{

			int i = this.Children.IndexOf(visual);
			if (i >= 0)
			{
				// we found the visual! Let's scroll it into view. First we need to know how big
				// each child is.
				Size finalSize = this.RenderSize;
				Size childSize = new Size(finalSize.Width, (finalSize.Height * 2) / this.Children.Count);

				// now we can calculate the vertical offset that we need and set it
				SetVerticalOffset(childSize.Height * i);

				// child size is always smaller than viewport, because that is what makes the Panel
				// an AnnoyingPanel.
				return rectangle;
			}


			throw new ArgumentException("Given visual is not in this Panel");
		}

		public void LineUp()
		{
			this.SetVerticalOffset(this.VerticalOffset - 1);
		}

		public void LineDown()
		{
			this.SetVerticalOffset(this.VerticalOffset + 1);
		}

		public void LineLeft()
		{
			this.SetHorizontalOffset(this.HorizontalOffset - 1);
		}

		public void LineRight()
		{
			this.SetHorizontalOffset(this.HorizontalOffset + 1);
		}

		public void MouseWheelUp()
		{
			SetVerticalOffset(this.VerticalOffset - 10);
		}

		public void MouseWheelDown()
		{
			SetVerticalOffset(this.VerticalOffset + 10);
		}

		public void MouseWheelLeft() { }

		public void MouseWheelRight() { }

		public void PageUp()
		{
			SetVerticalOffset(this.VerticalOffset - 20);
		}

		public void PageDown()
		{
			this.SetVerticalOffset(this.VerticalOffset + 20);
		}

		public void PageLeft()
		{
			this.SetHorizontalOffset(this.HorizontalOffset - 20);
		}

		public void PageRight()
		{
			this.SetHorizontalOffset(this.HorizontalOffset + 20);
		}

		public void SetHorizontalOffset(double offset)
		{
			if (offset < 0 || _viewport.Width >= _extent.Width)
			{
				offset = 0;
			}
			else
			{
				if (offset + _viewport.Width >= _extent.Width)
				{
					offset = _extent.Width - _viewport.Width;
				}
			}

			this.HorizontalOffset = offset;

			if (this.ScrollOwner != null)
				this.ScrollOwner.InvalidateScrollInfo();

			this._transform.X = -offset;
		}

		public void SetVerticalOffset(double offset)
		{
			if (offset < 0 || _viewport.Height >= _extent.Height)
			{
				offset = 0;
			}
			else
			{
				if (offset + _viewport.Height >= _extent.Height)
				{
					offset = _extent.Height - _viewport.Height;
				}
			}

			this.VerticalOffset = offset;

			if (this.ScrollOwner != null)
				this.ScrollOwner.InvalidateScrollInfo();

			this._transform.Y = -offset;
		}

		#endregion Methods

		#region Events


		#endregion Events

		#region Properties



		public bool CanHorizontallyScroll
		{
			get;
			set;
		}

		public bool CanVerticallyScroll
		{
			get;
			set;
		}

		public double ExtentHeight
		{
			get;
			private set;
		}

		public double ExtentWidth
		{
			get;
			private set;
		}

		public double HorizontalOffset
		{
			get;
			private set;
		}

		public ScrollViewer ScrollOwner
		{
			get;
			set;
		}

		public double VerticalOffset
		{
			get;
			private set;
		}

		public double ViewportHeight
		{
			get;
			private set;
		}

		public double ViewportWidth
		{
			get;
			private set;
		}

		#endregion Properties
	}
}
